#!/usr/bin/env python
# -*- coding: utf-8 -*-
#  user_helper.py
#  description

#  Created by zhouzongli633 on 2020/8/7 5:09 下午.
#  Copyright ©Intellectus All rights reserved.
import json
import random
import string
import datetime
import requests
from threading import Thread

from Baby.models import Babies
from Baby.models import Users
from Baby.models import UsersBabies
from Common.emailManager import Hotmail, send_invitation_code
from Common.jwt_auth import create_token
from Common.logger import app_log
from User.models import UserFamilyInvitationCode
from NICU2HOME import configs


def process_tokens(user):
    try:
        payload = {
            "id": user.id,
            "email": user.email,
            "security_code": user.security_code
        }
        access_token = create_token(payload, 120)
        refresh_token = "".join([random.choice(string.digits + string.ascii_letters) for i in range(128)])
        user.token_expiry_time = datetime.datetime.utcnow() + datetime.timedelta(minutes=120)
        user.token_scope = 'public'
        user.access_token = access_token
        user.refresh_token = refresh_token
        user.save()
        return {
            'access_token': user.access_token,
            'refresh_token': user.refresh_token
        }
    except Exception as e:
        raise e


def create_family_member(params):
    try:
        member = Users.objects.filter(id=params['user_id']).first()
        if not member:
            return None, None
        security_code = create_invitation_code()
        while True:
            user_exists = Users.objects.filter(security_code=security_code).first()
            app_log.info("security_code:{}".format(security_code))
            if not user_exists:
                app_log.info("security_code:{} not used".format(security_code))
                break
            security_code = create_invitation_code()
        family_user = Users(
            full_name=params['full_name'],
            email=params['email'],
            relationship=params['relationship'],
            security_code=security_code
        )
        if not member.spouse_id and (
                params['relationship'].lower() == 'father' or params['relationship'].lower() == 'mother'):
            member.spouse_id = family_user.id
            family_user.spouse_id = member.id
        member.save()
        family_user.save()
        return member, family_user
    except Exception as e:
        raise e


def create_invitation(member, family_user):
    invitation_code_created = False
    status = None
    looping_count = 0
    date = datetime.datetime.utcnow()

    while True:
        if looping_count >= 5:
            break
        looping_count += 1
        try:
            six_digits_code = family_user.security_code
            ufic = UserFamilyInvitationCode(
                invitation_code=six_digits_code,
                security_code=member.security_code,
                created_at=date,
                updated_at=date
            )
            ufic.save()
            add_babies_to_family_member(family_user, member)

            thr = Thread(target=send_invitation_code,
                         args=(family_user.email, six_digits_code, family_user.full_name, member.email,
                               member.full_name))
            thr.start()

            invitation_code_created = True
            return {'code_created': invitation_code_created, status: status}
        except Exception as e:
            app_log.exception(e)
            invitation_code_created = False
            status = e.args
            return {'code_created': invitation_code_created, status: status}


def create_invitation_code():
    return random.randint(100000, 999999)
    # return "".join(random.sample([x for x in string.ascii_uppercase + string.digits], 6))


def add_babies_to_family_member(family_member, user):
    babies = UsersBabies.objects.filter(users_id=user.id).all()
    for baby in babies:
        user_baby = UsersBabies(
            users_id=family_member.id,
            babies_id=baby.id,
            family_id=baby.family_id
        )
        user_baby.save()


def get_all_invited_members(user_id, check_for_baby=True):
    family_members = [user_id]
    all_babies = UsersBabies.objects.filter(users_id=user_id).all().values_list('babies_id', flat=True)
    if all_babies and check_for_baby:
        app_log.info("Babies were present:{}".format(all_babies))
        family_members = UsersBabies.objects.filter(babies__in=all_babies).all().values_list('babies_id', flat=True)
        family_members = list(set(family_members))
    else:
        user = Users.objects.filter(id=user_id).first()
        for member in UserFamilyInvitationCode.objects.filter(security_code=user.security_code):
            family = Users.objects.filter(security_code=member.invitation_code)
            if family:
                family_members.append(family.id)
                if family.relationship.lower() == 'father' or family.relationship.lower() == 'mother':
                    for member1 in UserFamilyInvitationCode.objects.filter(security_code=family.security_code):
                        family1 = Users.objects.filter(security_code=member1.invitation_code)
                        if family1:
                            family_members.append(family1.id)

        for member in UserFamilyInvitationCode.objects.filter(invitation_code=user.security_code):
            family = Users.objects.filter(security_code=member.security_code)
            if family:
                family_members.append(family.id)
                if family.relationship.lower() == 'father' or family.relationship.lower() == 'mother':
                    for member1 in UserFamilyInvitationCode.objects.filter(security_code=family.security_code):
                        family1 = Users.objects.filter(security_code=member1.invitation_code)
                        if family1:
                            family_members.append(family1.id)

        family_members = list(set(family_members))
    return family_members


def pending_survey(user_id):
    user = Users.objects.filter(id=user_id).first()
    if not user:
        return {}

    params = {'email': user.email}
    babies = UsersBabies.objects.filter(users_id=user_id).values('baby_id').all()
    babysense_ids = Babies.objects.filter(id=babies).values('babysense_id').all()
    params['babysense_ids'] = ",".join(str(i) for i in babysense_ids)
    # todo - pending_survey
    url = configs.babysense['url'] + configs.babysense['pending_surveys']
    resp = requests.post(url, data=json.dumps(params))
    if resp.status_code == 200:
        return json.loads(resp.content)
    else:
        return {}


def fetch_babies_with_user(user):
    ret = []
    if not user:
        return ret
    user_babys = user.users_babies.all()
    baby_ids = [i.babies_id for i in user_babys]
    records = Babies.objects.filter(id__in=baby_ids).all()
    ret = [it.baby_tojson() for it in records]
    return ret


def fetch_user_wit_baby(baby_id):
    baby = Babies.objects.filter(id=baby_id).first()
    if not baby:
        return {}
    user_babys = UsersBabies.objects.filter(users=baby)
    user_ids = [i.users_id for i in user_babys]
    ret = Users.objects.filter(id__in=user_ids).all()
    return ret


def get_all_family_members(user_id):
    family_members = []
    family_members.append(int(user_id))
    all_babies = [user_baby.babies_id for user_baby in UsersBabies.objects.filter(users_id=user_id).all()]
    if all_babies:
        app_log.info("Babies were present:{}".format(all_babies))

        records = UsersBabies.objects.filter(babies_id__in=all_babies).all()
        for user in records:
            family_members.append(user.users_id)

    else:
        user = Users.objects.get(user_id=user_id)
        for member in UserFamilyInvitationCode.objects.filter(security_code=user.security_code).all():
            family = Users.objects.filter(security_code=member.invitation_code).first()
            if family and family.password:
                family_members.append(family.id)
                if family.relationship.lower() == 'mother' or family.relationship.lower() == 'father':
                    for member1 in UserFamilyInvitationCode.objects.filter(security_code=family.security_code).all():
                        family1 = Users.objects.filter(security_code=member1.invitation_code).first()
                        if family1 and family1.password:
                            family_members.append(family1.id)

        for member in UserFamilyInvitationCode.objects.filter(invitation_code=user.security_code).all():
            family = Users.objects.filter(security_code=member.security_code).first()
            if family and family.password:
                family_members.append(family.id)
                if family.relationship.lower() == 'mother' or family.relationship.lower() == 'father':
                    for member1 in UserFamilyInvitationCode.objects.filter(security_code=family.security_code).all():
                        family1 = Users.objects.filter(security_code=member1.invitation_code).first()
                        if family1 and family1.password:
                            family_members.append(family1.id)

    family_members = list(set(family_members))
    return family_members


def nps_needed(user):
    pass
